#pragma ident "$Id: SolverMWAR.hpp 2648 2011-06-09 08:01:41Z shjzhang $"

/**
 * @file SolverMWAR.hpp
 * General Solver.
 */

#ifndef GPSTK_SolverMWAR_HPP
#define GPSTK_SolverMWAR_HPP

//============================================================================
//
//  Revision
//
//  2019/08/13  
//  make a generic PPP solver for multiple-gnss data.  
//  shjzhang    
//
//============================================================================


#include "SolverBase.hpp"
#include "TypeID.hpp"
#include "ProcessingClass.hpp"
#include "EquationSystem.hpp"
#include "StochasticModel.hpp"
#include "SimpleKalmanFilter.hpp"
#include "PartialAR.hpp"


namespace gpstk
{


          // type definition for usage in other program
   typedef std::map<CommonTime, VariableDataMap > epochVarDataMap;
   typedef std::map<CommonTime, CovarianceDataMap > epochCovDataMap;

   class SolverMWAR : public SolverBase, public ProcessingClass
   {
   public:

      SolverMWAR()
          : firstTime(true), 
            forwardProcessing(true),
            mwType(TypeID::MW12), 
            satSys(SatelliteSystem::GPS), 
            pObsStream(NULL), 
            pAmbStream(NULL), pAmbStreamSmoothed(NULL),                      
            pFixedAmbStream(NULL), pFixedAmbStreamSmoothed(NULL),                      
            pFixedInfoStream(NULL), pFixedInfoStreamSmoothed(NULL)
      {
         Init();
      }

         /** Explicit constructor.
          *
          * @param equation      Object describing the equations to be solved.
          * 
          * as default, resetInterval is set a very large value, if you want
          * to test the convergence of PPP, you can change the reset Interval.
          */
      SolverMWAR(TypeID& type, SatelliteSystem::Systems sys) 
          : mwType(type), satSys(sys)
      {
          Init();
      };


         /** Returns a reference to a gnnsRinex object after solving
          *  the previously defined equation system.
          *
          * @param gData    Data object holding the data.
          */
      virtual void Process( commonHeader& comHeader, gnssRinex& gData )
         noexcept(false);


         /** Returns a reference to a gnnsRinex object after solving
          *  the previously defined equation system.
          *
          * @param gData    Data object holding the data.
          */
      virtual void PostProcess( commonHeader& comHeader )
         noexcept(false)
      {
          PostProcess();
      };

      void smoothSolution( Vector<double>& oldStateVec,
                           Matrix<double>& oldCovMatrix,
                           Vector<double>& smoothedStateVec,
                           Matrix<double>& smoothedCovMatrix);

      virtual gnssRinex& Process(gnssRinex& gRin)
      {
          preCompute(gRin);
          Compute(gRin);
          postCompute(gRin);
          return gRin;
      };

      virtual void PostProcess()
         noexcept(false);

         /** Code to be executed before 'Compute()' method.
          *
          * @param gData    Data object holding the data.
          */
      virtual gnssRinex& preCompute( gnssRinex& gRin )
         noexcept(false);


         /** Code to be executed after 'Compute()' method.
          *
          * @param gData    Data object holding the data.
          */
      virtual gnssRinex& postCompute( gnssRinex& gRin )
         noexcept(false);


         /** Returns a reference to a gnssRinex object after computing .
          *
          * @param gData    Data object holding the data.
          */
      virtual gnssRinex& Compute( gnssRinex& gRin )
         noexcept(false);



         /// This method resets the filter, setting all variance values in
         /// covariance matrix to a very high level.
      virtual SolverMWAR& reset(void)
      { 
          firstTime = true;
          return (*this); 
      };

       /** Method to set a TypeID to be required. This method will erase
        *  previous required types.
        *
        * @param type      TypeID to be required.
        */
      virtual SolverMWAR& setType( const TypeID& type,
                                 const SatelliteSystem::Systems& sys)
      {
          satSys = sys;
          mwType = type;
          Init();

          return (*this);
      };

      VariableEstDataMap getAmbs(Vector<double>& solution,
                                Matrix<double>& covMatrix);

      void convertToBLCIndexed(VariableDataMap& fixedVarData,
                               VariableDataMap& blcIndexedData);

      void getRecBias( Vector<double>& solution,
                       TypeID& recType,
                       double& recBias );


         /// Returns an index identifying this object.
      virtual void setUpEquations(void) ;

      virtual SolverMWAR& setMWStream(std::ofstream* pStream)
      {
          pObsStream = pStream;
      }

      virtual SolverMWAR& setAmbStream(std::ofstream* pStream)
      {
          pAmbStream = pStream;
          return (*this);
      }

      virtual SolverMWAR& setAmbStreamSmoothed(std::ofstream* pStream)
      {
          pAmbStreamSmoothed = pStream;
          return (*this);
      }

      virtual SolverMWAR& setFixedAmbStream(std::ofstream* pStream)
      {
          pFixedAmbStream = pStream;
          return (*this);
      }

      virtual SolverMWAR& setFixedAmbStreamSmoothed(std::ofstream* pStream)
      {
          pFixedAmbStreamSmoothed = pStream;
          return (*this);
      }

      virtual SolverMWAR& setFixedInfoStream(std::ofstream* pStream)
      {
          pFixedInfoStream = pStream;
          return (*this);
      }

      virtual SolverMWAR& setFixedInfoStreamSmoothed(std::ofstream* pStream)
      {
          pFixedInfoStreamSmoothed = pStream;
          return (*this);
      }

      void printObs( std::ofstream* outStr, 
                     const CommonTime& epoch, 
                     gnssRinex& gData);

      void printAmbs( std::ofstream* outStr,
                           const CommonTime& epoch,
                           VariableEstDataMap& ambEstData);
    
      void printFixedAmbs( std::ofstream* outStr,
                           const CommonTime& epoch,
                           VariableEstDataMap& ambEstData,
                           VariableDataMap& fixedAmbData);

      void printFixedInfo( std::ofstream* outStr,
                           const CommonTime& epoch,
                           TypeID recType,
                           double recBias,
                           int numAmb,
                           int numFixed);

      // get ambEstData
      virtual VariableDataMap getCurrentFixedAmbData()
      {
          return currentFixedAmbs;
      };

      virtual VariableDataMap getAllFixedAmbData()
      {
          return globalFixedAmbs;
      };

         /// Returns an index identifying this object.
      virtual void Init(void) ;

         /// Returns an index identifying this object.
      virtual int getIndex(void) const;

         /// Returns a string identifying this object.
      virtual std::string getClassName(void) const;

         /// Destructor.
      virtual ~SolverMWAR() {};


   protected:

      /// Boolean indicating if this filter was run at least once
      bool firstTime;
      bool postProcessing;
      double thresholdVar;

      TypeID mwType;
      TypeID ambType;
      TypeID recType;

         /// Enum indicating the datum saystem
      SatelliteSystem::Systems satSys;

      VariableSet currentUnkSet;
      VariableSet oldUnkSet;

      std::ofstream* pObsStream;

      std::ofstream* pAmbStream;
      std::ofstream* pAmbStreamSmoothed;
      std::ofstream* pFixedAmbStream;
      std::ofstream* pFixedAmbStreamSmoothed;
      std::ofstream* pFixedInfoStream;
      std::ofstream* pFixedInfoStreamSmoothed;
      
      CommonTime firstEpoch;

      VariableDataMap currentFixedAmbs;
      VariableDataMap globalFixedAmbs;

      VariableEstDataMap globalAmbEstData;

   private:

      double wavelength;

         /// State Transition Matrix (PhiMatrix)
      Matrix<double> phiMatrix;

         /// Noise covariance matrix (QMatrix)
      Matrix<double> qMatrix;

         /// Geometry matrix
      Matrix<double> hMatrix;

         /// Weights matrix
      Matrix<double> rMatrix;

         /// Measurements vector (Prefit-residuals)
      Vector<double> measVector;

         /// Map holding state information
      VariableDataMap stateMap;

         /// Map holding covariance information
      CovarianceDataMap covMap;

         // Predicted state
      Vector<double> xhatminus;

         // Predicted covariance.
      Matrix<double> Pminus;

         // A posteriori state
      Vector<double> xhat;

         // A posteriori covariance.
      Matrix<double> P;

      // default model for variable define
      WhiteNoiseModel defaultModel;

      // GPS LC ambiguity
      PhaseAmbiguityModel BWL12GPSModel;
      PhaseAmbiguityModel BWL15GPSModel;

      PhaseAmbiguityModel BWL15GALModel;
      PhaseAmbiguityModel BWL17GALModel;
      PhaseAmbiguityModel BWL18GALModel;
      PhaseAmbiguityModel BWL16GALModel;

      PhaseAmbiguityModel BWL27BDSModel;
      PhaseAmbiguityModel BWL26BDSModel;


/*
      StochasticModel bias12GPSModel;
      StochasticModel bias15GPSModel;

      StochasticModel bias15GALModel;
      StochasticModel bias17GALModel;
      StochasticModel bias18GALModel;
      StochasticModel bias16GALModel;

      StochasticModel bias27BDSModel;
      StochasticModel bias26BDSModel;
*/

      WhiteNoiseModel wnBiasModel;
      StochasticModel constBiasModel;

      bool forwardProcessing;
      epochGnssRinexMap forwardRinexData;
      epochVectorMap forwardStateData;
      epochMatrixMap forwardCovData;


      PartialAR       partialAR;

         /// Equation system
      EquationSystem equSystem;

         /// Initial index assigned to this class.
      static int classIndex;

         /// Index belonging to this object.
      int index;

         /// Sets the index and increment classIndex.
      void setIndex(void)
      { index = classIndex++; };


   }; // End of class 'SolverMWAR'

      //@}

}  // End of namespace gpstk
#endif   // GPSTK_SolverMWAR_HPP
